
#ifndef _TW_VECTOR4D_H_
#define _TW_VECTOR4D_H_
#pragma once



class TwVector4d : public D3DXVECTOR4
{
public:

	//--------------------------------------------------
	// Creators...
	//--------------------------------------------------

	TwVector4d(){};
	TwVector4d(const TwVector4d& vec):D3DXVECTOR4(vec.x, vec.y, vec.z, vec.w){};
	TwVector4d(float _x, float _y, float _z, float _w):D3DXVECTOR4(_x,_y,_z,_w){};
	TwVector4d(TwVector3d _xyz, float _w):D3DXVECTOR4(_xyz.x, _xyz.y, _xyz.z, _w){};
	~TwVector4d(void){};

	//--------------------------------------------------
	// Aliases...
	//--------------------------------------------------

	// aliases
	TwVector2d& vec2() {return *((TwVector2d*)this);}
	TwVector3d& vec3() {return *((TwVector3d*)this);}
	operator TwVector2d& () {return vec2();}
	operator TwVector3d& () {return vec3();}

	const TwVector2d& vec2()const {return *((TwVector2d*)this);}
	const TwVector3d& vec3()const {return *((TwVector3d*)this);}
	operator const TwVector2d&()const {return vec2();}
	operator const TwVector3d&()const {return vec3();}

	const TwVector4d& operator *= (const TwVector4d& vec);
	const TwVector4d& operator /= (const TwVector4d& vec);
	const TwVector4d& operator *= (float v);
	const TwVector4d& operator /= (float v);

	//--------------------------------------------------
	// Mutators...
	//--------------------------------------------------

	void set(float _x, float _y, float _z, float _w);
	void clear(void);
	void setToAbsoluteValue();
	void invert();
	void negate();

	//--------------------------------------------------
	// Calculations\Operations...
	//--------------------------------------------------

	// testing operations
	float maxValue()const;
	float minValue()const;
	bool isClear()const;

	// length and distance calculations
	void normalize();
	float length()const;
	float lengthSquared()const;
	float distance(const TwVector4d& vec)const;
	float distanceSquared(const TwVector4d& vec)const;

	// dot and cross product
	float dotProduct(const TwVector4d& vec)const;
	float dotProduct(const TwVector3d& vec)const;
	void crossProduct(const TwVector4d& vec_b);
	void crossProduct(const TwVector4d& vec_a, const TwVector4d& vec_b);

	// angle operations (only valid for float, normalized versions)
	void computeHeadingAndPitch(float& heading, float& pitch)const;
	void setFromHeadingAndPitch(float heading, float pitch);
	void computeSphericalCoords(float& longitude, float& latitude)const;
	void setFromSphericalCoords(float longitude, float latitude);

	// reflect against the normal of a plane
	void reflect(const TwVector3d& normal);
	void reflect(const TwVector4d& source, const TwVector3d& normal);

	// refract through the normal of a plane
	void refract(const TwVector3d& normal, float incident, float transmitted);
	void refract(const TwVector4d& source, const TwVector3d& normal, float incident, float transmitted);

	// project along a normal vector
	void project(const TwVector3d& normal);
	void project(const TwVector4d& source, const TwVector3d& normal);

	// linear interpretation (integer scale from 0-100, real scale from 0-1)
	void lerp(const TwVector4d& source_b, float scale);
	void lerp(const TwVector4d& source_a, const TwVector4d& source_b, float scale);

	// create a normal to a plane given three points in clockwise order
	void createNormal(const TwVector4d& a, const TwVector4d& b, const TwVector4d& c);

	// create a normal given two vectors in clockwise order
	void createNormal(const TwVector4d& a, const TwVector4d& b);

	// test whether the vector is in the positive half-space of a normal
	bool testPositiveHalfSpace(const TwVector3d& normal)const;

	// compare with another vector using an optional epsilon value
	bool comparePosition(const TwVector4d& source)const;
	bool comparePosition(const TwVector4d& source, float epsilon)const;
	bool compareLength(const TwVector4d& source)const;
	bool compareLength(const TwVector4d& source, float epsilon)const;
	bool compareDirection(const TwVector4d& source)const;
	bool compareDirection(const TwVector4d& source, float epsilon)const;
	bool compareToZero()const;
	bool compareToZero(float epsilon)const;

	// set to the lesser components of two inputs
	void setMinByValue(const TwVector4d& source_b);
	void setMinByValue(const TwVector4d& source_a, const TwVector4d& source_b);
	// set to the lesser of two inputs (using length)
	void setMinByLength(const TwVector4d& source_b);
	void setMinByLength(const TwVector4d& source_a, const TwVector4d& source_b);

	// set to the greater components of two inputs
	void setMaxByValue(const TwVector4d& source_b);
	void setMaxByValue(const TwVector4d& source_a, const TwVector4d& source_b);
	// set to the greater of two inputs (using length)
	void setMaxByLength(const TwVector4d& source_b);
	void setMaxByLength(const TwVector4d& source_a, const TwVector4d& source_b);

};
#endif